﻿using System;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearAlgebra.Generic;

namespace innovations.util.exts.msft
{
    public static class PrimitiveTypesExt
    {
        public static DenseVector PointwiseAddition(this int j, DenseVector v)
        {
            DenseVector temp = new DenseVector(v.Count);
            for (int i = 0; i < v.Count; i++)
            {
                temp[i] = v[i] + j;
            }
            return temp;
        }

        public static Matrix<double> PointwiseAddition(this int k, Matrix<double> m)
        {
            DenseMatrix temp = new DenseMatrix(m.RowCount, m.ColumnCount);
            for (int i = 0; i < m.RowCount; i++)
            {
                for (int j = 0; j < m.ColumnCount; j++)
                {
                    temp[i, j] = m[i, j] + k;
                }
            }
            return temp;
        }

        public static Vector<double> PointwiseAddition(this int j, Vector<double> v)
        {
            DenseVector temp = new DenseVector(v.Count);
            for (int i = 0; i < v.Count; i++)
            {
                temp[i] = v[i] + j;
            }
            return temp;
        }

        public static DenseVector PointwiseSubtraction(this int j, DenseVector v)
        {
            DenseVector temp = new DenseVector(v.Count);
            for (int i = 0; i < v.Count; i++)
            {
                temp[i] = j - v[i];
            }
            return temp;
        }

        public static Vector<double> PointwiseSubtraction(this int j, Vector<double> v)
        {
            DenseVector temp = new DenseVector(v.Count);
            for (int i = 0; i < v.Count; i++)
            {
                temp[i] = j - v[i];
            }
            return temp;
        }

        public static DenseMatrix PointwiseSubtraction(this int j, DenseMatrix m)
        {
            DenseMatrix temp = new DenseMatrix(m.RowCount, m.ColumnCount);
            for (int i = 0; i < m.RowCount; i++)
            {
                for (int k = 0; k < m.ColumnCount; k++)
                    temp[i, k] = j - m[i, k];
            }
            return temp;
        }

        public static Matrix<double> PointwiseSubtraction(this int j, Matrix<double> m)
        {
            DenseMatrix temp = new DenseMatrix(m.RowCount, m.ColumnCount);
            for (int i = 0; i < m.RowCount; i++)
            {
                for (int k = 0; k < m.ColumnCount; k++)
                    temp[i, k] = j - m[i, k];
            }
            return temp;
        }

        public static DenseVector PointwiseMultiplication(this int j, DenseVector v)
        {
            double j_double = Convert.ToDouble(j);
            return j_double.PointwiseMultiplication(v);
        }

        public static DenseVector PointwiseMultiplication(this double j, DenseVector v)
        {
            DenseVector temp = new DenseVector(v.Count);
            for (int i = 0; i < v.Count; i++)
            {
                temp[i] = j * v[i];
            }
            return temp;
        }

        public static Vector<double> PointwiseMultiplication(this int j, Vector<double> v)
        {
            DenseVector temp = new DenseVector(v.Count);
            for (int i = 0; i < v.Count; i++)
            {
                temp[i] = j * v[i];
            }
            return temp;
        }

        public static Matrix<double> PointwiseMultiplication(this int k, Matrix<double> v)
        {
            double k_double = Convert.ToDouble(k);
            return k_double.PointwiseMultiplication(v);
        }

        public static Matrix<double> PointwiseMultiplication(this double k, Matrix<double> v)
        {
            DenseMatrix temp = new DenseMatrix(v.RowCount, v.ColumnCount);
            for (int i = 0; i < v.RowCount; i++)
            {
                for (int j = 0; j < v.ColumnCount; j++)
                {
                    temp[i, j] = k * v[i, j];
                }
            }
            return temp;
        }

        public static DenseVector PointwiseDivision(this int j, DenseVector v)
        {
            DenseVector temp = new DenseVector(v.Count);
            for (int i = 0; i < v.Count; i++)
            {
                temp[i] = j / v[i];
            }
            return temp;
        }

        public static Vector<double> PointwiseDivision(this int j, Vector<double> v)
        {
            DenseVector temp = new DenseVector(v.Count);
            for (int i = 0; i < v.Count; i++)
            {
                temp[i] = j / v[i];
            }
            return temp;
        }

        public static Matrix<double> PointwiseDivision(this int k, Matrix<double> m)
        {
            DenseMatrix temp = new DenseMatrix(m.RowCount, m.ColumnCount);
            for (int i = 0; i < m.RowCount; i++)
            {
                for (int j = 0; j < m.ColumnCount; j++)
                {
                    temp[i, j] = k / m[i, j];
                }
            }
            return temp;
        }
    }
}
